50static char *option[N_OPTIONS] = {
56 "Usage: sddscombinelogfiles [<SDDSinputfilelist>] [<SDDSoutputfile>]\n"
57 " [-pipe=[output]] [-overwrite]\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"
61 " -pipe=[output] Specify the pipe output.\n"
62 " -overwrite Overwrite the output file if it already exists.\n\n"
64 " sddscombinelogfiles input1.sdds input2.sdds output.sdds -overwrite\n\n"
65 "Link date: " __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
"\n";
67int main(
int argc,
char **argv) {
71 KEYED_EQUIVALENT **keyGroup = NULL;
73 char **inputfile = NULL;
75 char *outputfile = NULL;
77 int64_t i, j, m, r, s;
78 unsigned long pipeFlags = 0;
83 double **timeValues = NULL;
84 double **dataValues = NULL;
87 char **dataNames = NULL;
88 char **uniqueDataName = NULL;
89 int uniqueDataNames = 0;
93 double *outputTimeValues = NULL;
94 double **outputDataValues = NULL;
95 int64_t allocated_rows = 0;
100 argc =
scanargs(&s_arg, argc, argv);
103 fprintf(stderr,
"%s", USAGE);
107 for (i_arg = 1; i_arg < argc; i_arg++) {
108 if (s_arg[i_arg].arg_type == OPTION) {
109 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
115 s_arg[i_arg].n_items - 1,
117 fprintf(stderr,
"Error: Invalid -pipe option syntax.\n");
120 if (pipeFlags & USE_STDIN) {
121 fprintf(stderr,
"Error: -pipe=in is not supported.\n");
126 fprintf(stderr,
"Error: Unrecognized option.\n%s", USAGE);
130 inputfile =
trealloc(inputfile,
sizeof(*inputfile) * (inputfiles + 1));
131 inputfile[inputfiles++] = s_arg[i_arg].list[0];
135 if (inputfiles > 1) {
136 if (!(pipeFlags & USE_STDOUT)) {
137 outputfile = inputfile[--inputfiles];
138 if (
fexists(outputfile) && !overwrite) {
139 fprintf(stderr,
"Error: Output file '%s' already exists. Use -overwrite to replace it.\n", outputfile);
143 }
else if (inputfiles == 1) {
144 if ((pipeFlags & USE_STDOUT) && outputfile) {
145 fprintf(stderr,
"Error: Too many filenames provided with -pipe=output.\n");
149 fprintf(stderr,
"Error: No input filenames provided.\n%s", USAGE);
153 for (i = 0; i < inputfiles; i++) {
160 if (columnname == NULL) {
165 if (columnnames > 3 || columnnames < 2) {
166 fprintf(stderr,
"Error: Unexpected number of columns in '%s'.\n", inputfile[i]);
170 if (columnnames == 2) {
171 if (strcmp(
"Time", columnname[0]) == 0) {
173 }
else if (strcmp(
"Time", columnname[1]) == 0) {
176 fprintf(stderr,
"Error: 'Time' column is missing in '%s'.\n", inputfile[i]);
181 if (columnnames == 3) {
182 if (strcmp(
"CAerrors", columnname[0]) == 0) {
183 if (strcmp(
"Time", columnname[1]) == 0) {
185 }
else if (strcmp(
"Time", columnname[2]) == 0) {
188 fprintf(stderr,
"Error: 'Time' column is missing in '%s'.\n", inputfile[i]);
191 }
else if (strcmp(
"CAerrors", columnname[1]) == 0) {
192 if (strcmp(
"Time", columnname[0]) == 0) {
194 }
else if (strcmp(
"Time", columnname[2]) == 0) {
197 fprintf(stderr,
"Error: 'Time' column is missing in '%s'.\n", inputfile[i]);
200 }
else if (strcmp(
"CAerrors", columnname[2]) == 0) {
201 if (strcmp(
"Time", columnname[0]) == 0) {
203 }
else if (strcmp(
"Time", columnname[1]) == 0) {
206 fprintf(stderr,
"Error: 'Time' column is missing in '%s'.\n", inputfile[i]);
210 fprintf(stderr,
"Error: 'CAerrors' column is missing in '%s'.\n", inputfile[i]);
215 while (SDDS_ReadTable(&SDDS_input) > 0) {
216 timeValues = realloc(timeValues,
sizeof(*timeValues) * (page + 1));
217 dataValues = realloc(dataValues,
sizeof(*dataValues) * (page + 1));
218 dataNames = realloc(dataNames,
sizeof(*dataNames) * (page + 1));
219 rows = realloc(rows,
sizeof(*rows) * (page + 1));
222 rows[page] = SDDS_RowCount(&SDDS_input);
224 if (rows[page] > 0) {
226 if (timeValues[page] == NULL) {
232 if (dataValues[page] == NULL) {
237 timeValues[page] = NULL;
238 dataValues[page] = NULL;
243 for (j = 0; j < columnnames; j++) {
257 for (page = 0; page < pages; page++) {
259 for (i = 0; i < uniqueDataNames; i++) {
260 if (strcmp(dataNames[page], uniqueDataName[i]) == 0) {
266 uniqueDataName = realloc(uniqueDataName,
sizeof(*uniqueDataName) * (uniqueDataNames + 1));
283 for (i = 0; i < uniqueDataNames; i++) {
290 outputDataValues = malloc(
sizeof(*outputDataValues) * uniqueDataNames);
291 if (uniqueDataNames == 1) {
293 for (page = 0; page < pages; page++) {
294 allocated_rows += rows[page];
297 outputTimeValues = malloc(
sizeof(*outputTimeValues) * allocated_rows);
298 outputDataValues[0] = malloc(
sizeof(*(outputDataValues[0])) * allocated_rows);
301 for (page = 0; page < pages; page++) {
302 for (j = 0; j < rows[page]; j++) {
303 outputTimeValues[i] = timeValues[page][j];
304 outputDataValues[0][i] = dataValues[page][j];
310 flag = malloc(
sizeof(*flag) * pages);
311 for (page = 0; page < pages; page++) {
312 flag[page] = calloc(rows[page],
sizeof(*(flag[page])));
315 array = malloc(
sizeof(*array) * uniqueDataNames);
316 arrayCount = calloc(uniqueDataNames,
sizeof(*arrayCount));
318 for (i = 0; i < uniqueDataNames; i++) {
319 for (page = 0; page < pages; page++) {
320 if (strcmp(dataNames[page], uniqueDataName[i]) == 0) {
322 if (arrayCount[i] == 1) {
323 array[i] = malloc(
sizeof(*(array[i])));
325 array[i] = realloc(array[i],
sizeof(*(array[i])) * arrayCount[i]);
327 array[i][arrayCount[i] - 1] = page;
332 for (i = 0; i < arrayCount[0]; i++) {
334 for (n = 1; n < uniqueDataNames; n++) {
335 for (m = 0; m < arrayCount[n]; m++) {
336 if ((i == m) && (rows[array[0][i]] == rows[array[n][m]]) && (rows[array[0][i]] > 10)) {
337 if ((timeValues[array[0][i]][0] == timeValues[array[n][m]][0]) &&
338 (timeValues[array[0][i]][1] == timeValues[array[n][m]][1]) &&
339 (timeValues[array[0][i]][rows[array[0][i]] - 2] == timeValues[array[n][m]][rows[array[n][m]] - 2]) &&
340 (timeValues[array[0][i]][rows[array[0][i]] - 1] == timeValues[array[n][m]][rows[array[n][m]] - 1])) {
342 for (r = 0; r < rows[array[n][m]]; r++) {
343 if (flag[array[n][m]][r]) {
346 flag[array[0][i]][r] += 1;
347 flag[array[n][m]][r] = 1;
352 for (r = 0; r < rows[array[n][m]]; r++) {
353 if (flag[array[n][m]][r]) {
358 flag[array[0][i]][row] += 1;
359 flag[array[n][m]][r] = 1;
365 for (j = 0; j < keyGroups; j++) {
366 free(keyGroup[j]->equivalent);
372 z = uniqueDataNames - 1;
373 for (n = 0; n < arrayCount[0]; n++) {
374 for (m = 0; m < rows[array[0][n]]; m++) {
375 if (flag[array[0][n]][m] >= z) {
381 outputTimeValues = malloc(
sizeof(*outputTimeValues) * allocated_rows);
382 for (i = 0; i < uniqueDataNames; i++) {
383 outputDataValues[i] = malloc(
sizeof(*(outputDataValues[i])) * allocated_rows);
387 for (i = 0; i < arrayCount[0]; i++) {
388 for (j = 0; j < rows[array[0][i]]; j++) {
389 if (flag[array[0][i]][j] >= z) {
390 outputTimeValues[s] = timeValues[array[0][i]][j];
391 outputDataValues[0][s] = dataValues[array[0][i]][j];
398 fprintf(stderr,
"Error: No matching 'Time' rows found in input files.\n");
404 for (n = 1; n < uniqueDataNames; n++) {
405 for (m = 0; m < arrayCount[n]; m++) {
406 for (r = 0; r < rows[array[n][m]]; r++) {
407 if (flag[array[n][m]][r]) {
410 outputDataValues[n][row] = dataValues[array[n][m]][r];
417 for (i = 0; i < uniqueDataNames; i++) {
421 for (j = 0; j < keyGroups; j++) {
422 if (keyGroup[j]->equivalent)
423 free(keyGroup[j]->equivalent);
428 for (page = 0; page < pages; page++) {
439 for (page = 0; page < pages; page++) {
440 if (timeValues[page])
441 free(timeValues[page]);
442 if (dataValues[page])
443 free(dataValues[page]);
444 free(dataNames[page]);
466 for (i = 0; i < uniqueDataNames; i++) {
467 if (!
SDDS_SetColumnFromDoubles(&SDDS_output, SDDS_SET_BY_NAME, outputDataValues[i], allocated_rows, uniqueDataName[i])) {
473 if (!SDDS_WriteTable(&SDDS_output)) {
484 for (i = 0; i < uniqueDataNames; i++) {
485 free(uniqueDataName[i]);
486 free(outputDataValues[i]);
488 free(outputTimeValues);
489 free(outputDataValues);
490 free(uniqueDataName);
493 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.