46static char *option[N_OPTIONS] = {
52 "Usage: sddscombinelogfiles [<SDDSinputfilelist>] [<SDDSoutputfile>]\n"
53 " [-pipe=[output]] [-overwrite]\n\n"
54 "This program combines data logger output files that are in the one-PV-per-file format.\n"
55 "Only the timestamps present in all input files are retained in the output file.\n\n"
57 " -pipe=[output] Specify the pipe output.\n"
58 " -overwrite Overwrite the output file if it already exists.\n\n"
60 " sddscombinelogfiles input1.sdds input2.sdds output.sdds -overwrite\n\n"
61 "Link date: " __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
"\n";
63int main(
int argc,
char **argv) {
67 KEYED_EQUIVALENT **keyGroup = NULL;
69 char **inputfile = NULL;
71 char *outputfile = NULL;
73 int64_t i, j, m, r, s;
74 unsigned long pipeFlags = 0;
79 double **timeValues = NULL;
80 double **dataValues = NULL;
83 char **dataNames = NULL;
84 char **uniqueDataName = NULL;
85 int uniqueDataNames = 0;
89 double *outputTimeValues = NULL;
90 double **outputDataValues = NULL;
91 int64_t allocated_rows = 0;
99 fprintf(stderr,
"%s", USAGE);
103 for (i_arg = 1; i_arg < argc; i_arg++) {
104 if (s_arg[i_arg].arg_type == OPTION) {
105 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
111 s_arg[i_arg].n_items - 1,
113 fprintf(stderr,
"Error: Invalid -pipe option syntax.\n");
116 if (pipeFlags & USE_STDIN) {
117 fprintf(stderr,
"Error: -pipe=in is not supported.\n");
122 fprintf(stderr,
"Error: Unrecognized option.\n%s", USAGE);
126 inputfile =
trealloc(inputfile,
sizeof(*inputfile) * (inputfiles + 1));
127 inputfile[inputfiles++] = s_arg[i_arg].list[0];
131 if (inputfiles > 1) {
132 if (!(pipeFlags & USE_STDOUT)) {
133 outputfile = inputfile[--inputfiles];
134 if (
fexists(outputfile) && !overwrite) {
135 fprintf(stderr,
"Error: Output file '%s' already exists. Use -overwrite to replace it.\n", outputfile);
139 }
else if (inputfiles == 1) {
140 if ((pipeFlags & USE_STDOUT) && outputfile) {
141 fprintf(stderr,
"Error: Too many filenames provided with -pipe=output.\n");
145 fprintf(stderr,
"Error: No input filenames provided.\n%s", USAGE);
149 for (i = 0; i < inputfiles; i++) {
156 if (columnname == NULL) {
161 if (columnnames > 3 || columnnames < 2) {
162 fprintf(stderr,
"Error: Unexpected number of columns in '%s'.\n", inputfile[i]);
166 if (columnnames == 2) {
167 if (strcmp(
"Time", columnname[0]) == 0) {
169 }
else if (strcmp(
"Time", columnname[1]) == 0) {
172 fprintf(stderr,
"Error: 'Time' column is missing in '%s'.\n", inputfile[i]);
177 if (columnnames == 3) {
178 if (strcmp(
"CAerrors", columnname[0]) == 0) {
179 if (strcmp(
"Time", columnname[1]) == 0) {
181 }
else if (strcmp(
"Time", columnname[2]) == 0) {
184 fprintf(stderr,
"Error: 'Time' column is missing in '%s'.\n", inputfile[i]);
187 }
else if (strcmp(
"CAerrors", columnname[1]) == 0) {
188 if (strcmp(
"Time", columnname[0]) == 0) {
190 }
else if (strcmp(
"Time", columnname[2]) == 0) {
193 fprintf(stderr,
"Error: 'Time' column is missing in '%s'.\n", inputfile[i]);
196 }
else if (strcmp(
"CAerrors", columnname[2]) == 0) {
197 if (strcmp(
"Time", columnname[0]) == 0) {
199 }
else if (strcmp(
"Time", columnname[1]) == 0) {
202 fprintf(stderr,
"Error: 'Time' column is missing in '%s'.\n", inputfile[i]);
206 fprintf(stderr,
"Error: 'CAerrors' column is missing in '%s'.\n", inputfile[i]);
211 while (SDDS_ReadTable(&SDDS_input) > 0) {
212 timeValues = realloc(timeValues,
sizeof(*timeValues) * (page + 1));
213 dataValues = realloc(dataValues,
sizeof(*dataValues) * (page + 1));
214 dataNames = realloc(dataNames,
sizeof(*dataNames) * (page + 1));
215 rows = realloc(rows,
sizeof(*rows) * (page + 1));
218 rows[page] = SDDS_RowCount(&SDDS_input);
220 if (rows[page] > 0) {
222 if (timeValues[page] == NULL) {
228 if (dataValues[page] == NULL) {
233 timeValues[page] = NULL;
234 dataValues[page] = NULL;
239 for (j = 0; j < columnnames; j++) {
253 for (page = 0; page < pages; page++) {
255 for (i = 0; i < uniqueDataNames; i++) {
256 if (strcmp(dataNames[page], uniqueDataName[i]) == 0) {
262 uniqueDataName = realloc(uniqueDataName,
sizeof(*uniqueDataName) * (uniqueDataNames + 1));
279 for (i = 0; i < uniqueDataNames; i++) {
286 outputDataValues = malloc(
sizeof(*outputDataValues) * uniqueDataNames);
287 if (uniqueDataNames == 1) {
289 for (page = 0; page < pages; page++) {
290 allocated_rows += rows[page];
293 outputTimeValues = malloc(
sizeof(*outputTimeValues) * allocated_rows);
294 outputDataValues[0] = malloc(
sizeof(*(outputDataValues[0])) * allocated_rows);
297 for (page = 0; page < pages; page++) {
298 for (j = 0; j < rows[page]; j++) {
299 outputTimeValues[i] = timeValues[page][j];
300 outputDataValues[0][i] = dataValues[page][j];
306 flag = malloc(
sizeof(*flag) * pages);
307 for (page = 0; page < pages; page++) {
308 flag[page] = calloc(rows[page],
sizeof(*(flag[page])));
311 array = malloc(
sizeof(*array) * uniqueDataNames);
312 arrayCount = calloc(uniqueDataNames,
sizeof(*arrayCount));
314 for (i = 0; i < uniqueDataNames; i++) {
315 for (page = 0; page < pages; page++) {
316 if (strcmp(dataNames[page], uniqueDataName[i]) == 0) {
318 if (arrayCount[i] == 1) {
319 array[i] = malloc(
sizeof(*(array[i])));
321 array[i] = realloc(array[i],
sizeof(*(array[i])) * arrayCount[i]);
323 array[i][arrayCount[i] - 1] = page;
328 for (i = 0; i < arrayCount[0]; i++) {
330 for (n = 1; n < uniqueDataNames; n++) {
331 for (m = 0; m < arrayCount[n]; m++) {
332 if ((i == m) && (rows[array[0][i]] == rows[array[n][m]]) && (rows[array[0][i]] > 10)) {
333 if ((timeValues[array[0][i]][0] == timeValues[array[n][m]][0]) &&
334 (timeValues[array[0][i]][1] == timeValues[array[n][m]][1]) &&
335 (timeValues[array[0][i]][rows[array[0][i]] - 2] == timeValues[array[n][m]][rows[array[n][m]] - 2]) &&
336 (timeValues[array[0][i]][rows[array[0][i]] - 1] == timeValues[array[n][m]][rows[array[n][m]] - 1])) {
338 for (r = 0; r < rows[array[n][m]]; r++) {
339 if (flag[array[n][m]][r]) {
342 flag[array[0][i]][r] += 1;
343 flag[array[n][m]][r] = 1;
348 for (r = 0; r < rows[array[n][m]]; r++) {
349 if (flag[array[n][m]][r]) {
354 flag[array[0][i]][row] += 1;
355 flag[array[n][m]][r] = 1;
361 for (j = 0; j < keyGroups; j++) {
362 free(keyGroup[j]->equivalent);
368 z = uniqueDataNames - 1;
369 for (n = 0; n < arrayCount[0]; n++) {
370 for (m = 0; m < rows[array[0][n]]; m++) {
371 if (flag[array[0][n]][m] >= z) {
377 outputTimeValues = malloc(
sizeof(*outputTimeValues) * allocated_rows);
378 for (i = 0; i < uniqueDataNames; i++) {
379 outputDataValues[i] = malloc(
sizeof(*(outputDataValues[i])) * allocated_rows);
383 for (i = 0; i < arrayCount[0]; i++) {
384 for (j = 0; j < rows[array[0][i]]; j++) {
385 if (flag[array[0][i]][j] >= z) {
386 outputTimeValues[s] = timeValues[array[0][i]][j];
387 outputDataValues[0][s] = dataValues[array[0][i]][j];
394 fprintf(stderr,
"Error: No matching 'Time' rows found in input files.\n");
400 for (n = 1; n < uniqueDataNames; n++) {
401 for (m = 0; m < arrayCount[n]; m++) {
402 for (r = 0; r < rows[array[n][m]]; r++) {
403 if (flag[array[n][m]][r]) {
406 outputDataValues[n][row] = dataValues[array[n][m]][r];
413 for (i = 0; i < uniqueDataNames; i++) {
417 for (j = 0; j < keyGroups; j++) {
418 if (keyGroup[j]->equivalent)
419 free(keyGroup[j]->equivalent);
424 for (page = 0; page < pages; page++) {
435 for (page = 0; page < pages; page++) {
436 if (timeValues[page])
437 free(timeValues[page]);
438 if (dataValues[page])
439 free(dataValues[page]);
440 free(dataNames[page]);
462 for (i = 0; i < uniqueDataNames; i++) {
463 if (!
SDDS_SetColumnFromDoubles(&SDDS_output, SDDS_SET_BY_NAME, outputDataValues[i], allocated_rows, uniqueDataName[i])) {
469 if (!SDDS_WriteTable(&SDDS_output)) {
480 for (i = 0; i < uniqueDataNames; i++) {
481 free(uniqueDataName[i]);
482 free(outputDataValues[i]);
484 free(outputTimeValues);
485 free(outputDataValues);
486 free(uniqueDataName);
489 if (inputfiles > 0) {
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.
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.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
#define SDDS_DOUBLE
Identifier for the double data type.
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
long fexists(const char *filename)
Checks if a file exists.
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)
long processPipeOption(char **item, long items, unsigned long *flags)
void free_scanargs(SCANNED_ARG **scanned, int argc)
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.