SDDSlib
Loading...
Searching...
No Matches
sddscollect.c
Go to the documentation of this file.
1/**
2 * @file sddscollect.c
3 * @brief Collects data from multiple columns into new grouped columns based on specified criteria.
4 *
5 * The program processes SDDS (Self Describing Data Sets) files, allowing users to collect
6 * data from various input columns and organize them into new output columns with specified
7 * suffixes, prefixes, or matching patterns. It supports options for pipeline processing,
8 * controlling warnings, and setting the major order of the output data.
9 *
10 * @usage
11 * sddscollect [options] [<input>] [<output>]
12 *
13 * @options
14 * -pipe=[input][,output]
15 * Use the standard SDDS toolkit pipe option for input and output.
16 *
17 * -collect={suffix=<string>|prefix=<string>|match=<string>}[,column=<newName>][,editCommand=<string>][,exclude=<wildcard>]...
18 * Collects columns based on the specified suffix, prefix, or matching pattern.
19 * - `suffix`: Selects columns ending with the given string.
20 * - `prefix`: Selects columns starting with the given string.
21 * - `match`: Selects columns matching the given wildcard pattern.
22 * - `column`: (Optional) Specifies the name of the new column. Defaults to the suffix or prefix.
23 * - `editCommand`: (Optional) Specifies a command to edit the column names.
24 * - `exclude`: (Optional) Excludes columns matching the given wildcard pattern.
25 *
26 * -nowarnings
27 * Suppresses warning messages.
28 *
29 * -majorOrder=row|column
30 * Specifies the major order of the output file. Can be either row-major or column-major.
31 *
32 * @copyright
33 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
34 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
35 *
36 * @license
37 * This file is distributed under the terms of the Software License Agreement
38 * found in the file LICENSE included with this distribution.
39 *
40 * @author M. Borland, R. Soliday, L. Emery
41 */
42
43#include "mdb.h"
44#include "SDDS.h"
45#include "SDDSutils.h"
46#include "scan.h"
47#include <ctype.h>
48
49static char *USAGE =
50 "Usage: sddscollect [options] [<input>] [<output>]\n\n"
51 "Options:\n"
52 " -pipe=[input][,output]\n"
53 " Use the standard SDDS toolkit pipe option for input and output.\n\n"
54 " -collect={suffix=<string>|prefix=<string>|match=<string>}\n"
55 " Collects columns based on the specified suffix, prefix, or matching pattern.\n"
56 " Additional parameters:\n"
57 " column=<newName> (Optional) Name of the new column. Defaults to suffix or prefix.\n"
58 " editCommand=<string> (Optional) Command to edit the column names.\n"
59 " exclude=<wildcard> (Optional) Exclude columns matching the wildcard pattern.\n\n"
60 " -nowarnings\n"
61 " Suppresses warning messages.\n\n"
62 " -majorOrder=row|column\n"
63 " Specifies the major order of the output file. Can be either row-major or column-major.\n\n"
64 "Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")";
65
66/* Enumeration for option types */
67enum option_type {
68 CLO_COLLECT,
69 CLO_PIPE,
70 CLO_NOWARNINGS,
71 CLO_MAJOR_ORDER,
72 N_OPTIONS
73};
74
75static char *option[N_OPTIONS] = {
76 "collect",
77 "pipe",
78 "nowarnings",
79 "majorOrder",
80};
81
82typedef struct
83{
84 char *part, *newColumn, *match, *editCommand, *exclude;
85 char **oldColumn;
86 void **data;
87 long oldColumns, targetIndex, size;
88 unsigned long flags;
90
91typedef struct
92{
93 char *name;
94 void *data;
95 long size, targetIndex;
97
98#define COLLECTION_SUFFIX 0x0001U
99#define COLLECTION_PREFIX 0x0002U
100#define COLLECTION_COLUMN 0x0004U
101#define COLLECTION_MATCH 0x0008U
102#define COLLECTION_EDIT 0x0010U
103#define COLLECTION_EXCLUDE 0x0020U
104
105long InitializeOutput(SDDS_DATASET *SDDSout, char *output, SDDS_DATASET *SDDSin, COLLECTION *collection, long collections, NEW_PARAMETER **newParameter, int *newParameters, char ***rootname, char ***units, long warnings);
106void CollectAndWriteData(SDDS_DATASET *SDDSout, COLLECTION *collection, long collections, NEW_PARAMETER *newParameter, int newParameters, char **rootname, char **units, long rootnames, int64_t inputRow, long origPage);
107void GetAndOrganizeData(SDDS_DATASET *SDDSin, COLLECTION *collection, long collections, NEW_PARAMETER *newParameter, int newParameters);
108char **ConfirmMatchingColumns(COLLECTION *collection, long collections, SDDS_DATASET *SDDSin, SDDS_DATASET *SDDSout, long *rootnames, char ***units, long warnings);
109
110int main(int argc, char **argv) {
111 long iArg, ic;
112 SDDS_DATASET SDDSin, SDDSout;
113 SCANNED_ARG *scanned;
114 unsigned long pipeFlags, flags, majorOrderFlag;
115 COLLECTION *collection;
116 NEW_PARAMETER *newParameter;
117 char **rootname, **units;
118 long collections, rootnames, code;
119 int newParameters = 0;
120 int64_t rows, row;
121 char *input, *output;
122 long warnings;
123 short columnMajorOrder = -1;
124
126
127 argc = scanargs(&scanned, argc, argv);
128 if (argc == 1) {
129 bomb(NULL, USAGE);
130 return EXIT_FAILURE;
131 }
132
133 input = output = NULL;
134 collection = NULL;
135 collections = 0;
136 pipeFlags = 0;
137 warnings = 1;
138
139 for (iArg = 1; iArg < argc; iArg++) {
140 if (scanned[iArg].arg_type == OPTION) {
141 /* process options here */
142 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
143 case CLO_MAJOR_ORDER:
144 majorOrderFlag = 0;
145 scanned[iArg].n_items--;
146 if (scanned[iArg].n_items > 0 &&
147 (!scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
148 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
149 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
150 SDDS_Bomb("Invalid -majorOrder syntax/values");
151 }
152 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
153 columnMajorOrder = 1;
154 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
155 columnMajorOrder = 0;
156 break;
157 case CLO_COLLECT:
158 if (!(collection = SDDS_Realloc(collection, sizeof(*collection) * (collections + 1)))) {
159 SDDS_Bomb("Memory allocation failure");
160 }
161 ic = collections;
162 collection[ic].newColumn = collection[ic].part = collection[ic].match = collection[ic].editCommand = NULL;
163 collection[ic].exclude = NULL;
164 if (--scanned[iArg].n_items == 0 ||
165 !scanItemList(&flags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
166 "suffix", SDDS_STRING, &collection[ic].part, 1, COLLECTION_SUFFIX,
167 "prefix", SDDS_STRING, &collection[ic].part, 1, COLLECTION_PREFIX,
168 "column", SDDS_STRING, &collection[ic].newColumn, 1, COLLECTION_COLUMN,
169 "match", SDDS_STRING, &collection[ic].match, 1, COLLECTION_MATCH,
170 "editcommand", SDDS_STRING, &collection[ic].editCommand, 1, COLLECTION_EDIT,
171 "exclude", SDDS_STRING, &collection[ic].exclude, 1, COLLECTION_EXCLUDE, NULL) ||
172 ((flags & COLLECTION_SUFFIX && flags & COLLECTION_PREFIX) ||
173 (flags & COLLECTION_SUFFIX && flags & COLLECTION_MATCH) ||
174 (flags & COLLECTION_PREFIX && flags & COLLECTION_MATCH))) {
175 SDDS_Bomb("Invalid -collect syntax");
176 }
177 if (flags & COLLECTION_MATCH &&
178 (!(flags & COLLECTION_EDIT) || !(flags & COLLECTION_COLUMN))) {
179 SDDS_Bomb("Invalid -collect syntax: must give editCommand and column with match");
180 }
181 collection[ic].flags = flags;
182 collections++;
183 break;
184 case CLO_PIPE:
185 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags)) {
186 SDDS_Bomb("Invalid -pipe syntax");
187 }
188 break;
189 case CLO_NOWARNINGS:
190 warnings = 0;
191 break;
192 default:
193 fprintf(stderr, "Invalid option seen: %s\n", scanned[iArg].list[0]);
194 exit(EXIT_FAILURE);
195 break;
196 }
197 } else {
198 if (!input)
199 input = scanned[iArg].list[0];
200 else if (!output)
201 output = scanned[iArg].list[0];
202 else
203 SDDS_Bomb("Too many filenames");
204 }
205 }
206
207 if (!collections) {
208 SDDS_Bomb("At least one -collect option must be given");
209 }
210
211 processFilenames("sddscollect", &input, &output, pipeFlags, !warnings, NULL);
212
213 if (!SDDS_InitializeInput(&SDDSin, input)) {
214 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
215 }
216
217 rootnames = InitializeOutput(&SDDSout, output, &SDDSin, collection, collections,
218 &newParameter, &newParameters, &rootname, &units, warnings);
219 if (columnMajorOrder != -1)
220 SDDSout.layout.data_mode.column_major = columnMajorOrder;
221 else
222 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
223
224 while ((code = SDDS_ReadPage(&SDDSin)) > 0) {
225 if (!SDDS_StartPage(&SDDSout, rootnames) ||
226 !SDDS_CopyParameters(&SDDSout, &SDDSin) ||
227 !SDDS_CopyArrays(&SDDSout, &SDDSin)) {
228 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
229 }
230 if ((rows = SDDS_CountRowsOfInterest(&SDDSin)) > 0) {
231 GetAndOrganizeData(&SDDSin, collection, collections, newParameter, newParameters);
232 for (row = 0; row < rows; row++) {
233 CollectAndWriteData(&SDDSout, collection, collections, newParameter, newParameters,
234 rootname, units, rootnames, row, code);
235 if (row != rows - 1 && !SDDS_StartPage(&SDDSout, rootnames)) {
236 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
237 }
238 }
239 } else if (!SDDS_WritePage(&SDDSout)) {
240 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
241 }
242 }
243 if (!code || !SDDS_Terminate(&SDDSout) || !SDDS_Terminate(&SDDSin)) {
244 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
245 }
246 return EXIT_SUCCESS;
247}
248
249void CollectAndWriteData(SDDS_DATASET *SDDSout, COLLECTION *collection, long collections,
250 NEW_PARAMETER *newParameter, int newParameters, char **rootname,
251 char **units, long rootnames, int64_t inputRow, long origPage) {
252 long ic, ip, ir;
253 if (rootnames) {
254 if (!SDDS_SetColumn(SDDSout, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, rootname, rootnames, "Rootname")) {
255 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
256 }
257 if (!SDDS_SetColumn(SDDSout, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, units, rootnames, "Units")) {
258 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
259 }
260 for (ic = 0; ic < collections; ic++) {
261 for (ir = 0; ir < rootnames; ir++) {
262 if (!SDDS_SetRowValues(SDDSout, SDDS_PASS_BY_REFERENCE | SDDS_SET_BY_INDEX,
263 ir, collection[ic].targetIndex,
264 ((char *)(collection[ic].data[ir])) + inputRow * collection[ic].size, -1)) {
265 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
266 }
267 }
268 }
269 }
270
271 for (ip = 0; ip < newParameters; ip++) {
272 if (!SDDS_SetParameters(SDDSout, SDDS_PASS_BY_REFERENCE | SDDS_SET_BY_NAME,
273 newParameter[ip].name,
274 ((char *)(newParameter[ip].data) + inputRow * newParameter[ip].size), NULL)) {
275 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
276 }
277 }
278 if (!SDDS_SetParameters(SDDSout, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME,
279 "OriginalPage", origPage, NULL) ||
280 !SDDS_WritePage(SDDSout)) {
281 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
282 }
283}
284
285void GetAndOrganizeData(SDDS_DATASET *SDDSin, COLLECTION *collection, long collections,
286 NEW_PARAMETER *newParameter, int newParameters) {
287 long ic, ip, ii;
288 for (ic = 0; ic < collections; ic++) {
289 for (ii = 0; ii < collection[ic].oldColumns; ii++) {
290 if (!(collection[ic].data[ii] = SDDS_GetInternalColumn(SDDSin, collection[ic].oldColumn[ii]))) {
291 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
292 }
293 }
294 }
295 for (ip = 0; ip < newParameters; ip++) {
296 if (!(newParameter[ip].data = SDDS_GetColumn(SDDSin, newParameter[ip].name))) {
297 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
298 }
299 }
300}
301
302long InitializeOutput(SDDS_DATASET *SDDSout, char *output, SDDS_DATASET *SDDSin,
303 COLLECTION *collection, long collections, NEW_PARAMETER **newParameter,
304 int *newParameters, char ***rootname, char ***units, long warnings) {
305 char **inputColumn, *partString;
306 long partLength, *inputLength;
307 int32_t inputColumns;
308 short *inputUsed;
309 long ic, ii, ip, inputsUsed, rootnames;
310 char *matchString, *excludeString;
311
312 partLength = 0;
313 inputLength = NULL;
314
315 if (!SDDS_InitializeOutput(SDDSout, SDDS_BINARY, 0, NULL, "sddscollect output", output) ||
316 !SDDS_TransferAllParameterDefinitions(SDDSout, SDDSin, 0) ||
317 !SDDS_TransferAllArrayDefinitions(SDDSout, SDDSin, 0)) {
318 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
319 }
320
321 if (!(inputColumn = SDDS_GetColumnNames(SDDSin, &inputColumns)) || inputColumns == 0) {
322 SDDS_Bomb("No columns in input file");
323 }
324 if (!(inputUsed = (short *)calloc(inputColumns, sizeof(*inputUsed))) ||
325 !(inputLength = (long *)calloc(inputColumns, sizeof(*inputLength)))) {
326 SDDS_Bomb("Memory allocation failure");
327 }
328 for (ii = 0; ii < inputColumns; ii++)
329 inputLength[ii] = strlen(inputColumn[ii]);
330
331 inputsUsed = 0;
332 matchString = NULL;
333 excludeString = NULL;
334 for (ic = 0; ic < collections; ic++) {
335 if (!collection[ic].newColumn)
336 SDDS_CopyString(&collection[ic].newColumn, collection[ic].part);
337 if ((partString = collection[ic].part))
338 partLength = strlen(partString);
339 if (collection[ic].match) {
340 matchString = collection[ic].match;
341 partLength = -1;
342 }
343 if (collection[ic].exclude) {
344 excludeString = collection[ic].exclude;
345 }
346 collection[ic].oldColumn = NULL;
347 collection[ic].oldColumns = 0;
348 for (ii = 0; ii < inputColumns; ii++) {
349 if (inputUsed[ii])
350 continue;
351 if (partLength >= inputLength[ii])
352 continue;
353 if (matchString) {
354 if (wild_match(inputColumn[ii], matchString)) {
355 if ((excludeString == NULL) || (!wild_match(inputColumn[ii], excludeString))) {
356 if (!(collection[ic].oldColumn = SDDS_Realloc(collection[ic].oldColumn,
357 sizeof(*collection[ic].oldColumn) * (collection[ic].oldColumns + 1)))) {
358 SDDS_Bomb("Memory allocation failure");
359 }
360 collection[ic].oldColumn[collection[ic].oldColumns] = inputColumn[ii];
361 inputUsed[ii] = 1;
362 inputsUsed++;
363 collection[ic].oldColumns++;
364 }
365 }
366 } else if (collection[ic].flags & COLLECTION_PREFIX) {
367 if (strncmp(partString, inputColumn[ii], partLength) == 0) {
368 if (!(collection[ic].oldColumn = SDDS_Realloc(collection[ic].oldColumn,
369 sizeof(*collection[ic].oldColumn) * (collection[ic].oldColumns + 1)))) {
370 SDDS_Bomb("Memory allocation failure");
371 }
372 collection[ic].oldColumn[collection[ic].oldColumns] = inputColumn[ii];
373 inputUsed[ii] = 1;
374 inputsUsed++;
375 collection[ic].oldColumns++;
376 }
377 } else {
378 if (strcmp(partString, inputColumn[ii] + inputLength[ii] - partLength) == 0) {
379 if (!(collection[ic].oldColumn = SDDS_Realloc(collection[ic].oldColumn,
380 sizeof(*collection[ic].oldColumn) * (collection[ic].oldColumns + 1)))) {
381 SDDS_Bomb("Memory allocation failure");
382 }
383 collection[ic].oldColumn[collection[ic].oldColumns] = inputColumn[ii];
384 inputUsed[ii] = 1;
385 inputsUsed++;
386 collection[ic].oldColumns++;
387 }
388 }
389 }
390 if (!collection[ic].oldColumns && warnings) {
391 fprintf(stderr, "Warning (sddscollect): No columns in input for %s %s\n",
392 collection[ic].flags & COLLECTION_PREFIX ? "prefix" : "suffix", collection[ic].part);
393 }
394 if (!(collection[ic].data = (void **)calloc(collection[ic].oldColumns, sizeof(*collection[ic].data)))) {
395 SDDS_Bomb("Memory allocation failure");
396 }
397 }
398
399 if ((*newParameters = inputColumns - inputsUsed)) {
400 *newParameter = (NEW_PARAMETER *)malloc(sizeof(**newParameter) * (*newParameters));
401 for (ii = ip = 0; ii < inputColumns; ii++) {
402 if (inputUsed[ii])
403 continue;
404 if (!SDDS_CopyString(&(*newParameter)[ip].name, inputColumn[ii]) ||
405 !SDDS_DefineParameterLikeColumn(SDDSout, SDDSin, inputColumn[ii], NULL) ||
406 ((*newParameter)[ip].targetIndex = SDDS_GetParameterIndex(SDDSout, inputColumn[ii])) < 0) {
407 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
408 }
409 (*newParameter)[ip].size = SDDS_GetTypeSize(SDDS_GetParameterType(SDDSout, (*newParameter)[ip].targetIndex));
410 ip++;
411 }
412 }
413
414 *rootname = ConfirmMatchingColumns(collection, collections, SDDSin, SDDSout, &rootnames, units, warnings);
415
416 if (SDDS_DefineParameter(SDDSout, "OriginalPage", NULL, NULL, NULL, NULL, SDDS_LONG, NULL) < 0) {
417 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
418 }
419 if (rootnames &&
420 (SDDS_DefineColumn(SDDSout, "Rootname", NULL, NULL, NULL, NULL, SDDS_STRING, 0) < 0 ||
421 SDDS_DefineColumn(SDDSout, "Units", NULL, NULL, NULL, NULL, SDDS_STRING, 0) < 0)) {
422 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
423 }
424 if (!SDDS_WriteLayout(SDDSout)) {
425 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
426 }
427 return rootnames;
428}
429
430char **ConfirmMatchingColumns(COLLECTION *collection, long collections, SDDS_DATASET *SDDSin,
431 SDDS_DATASET *SDDSout, long *rootnames, char ***units, long warnings) {
432 long ic, ip, ii, partLength;
433 char **rootname, editBuffer[1024];
434 char saveChar;
435
436 partLength = 0;
437 rootname = NULL;
438 *units = NULL;
439 *rootnames = 0;
440 if (!collections)
441 return NULL;
442 for (ic = 0; ic < collections; ic++) {
443 if (!collection[ic].oldColumns)
444 continue;
445 if (collection[ic].part)
446 partLength = strlen(collection[ic].part);
447 if (collection[ic].part && collection[ic].flags & COLLECTION_SUFFIX) {
448 /* sort collection according to truncated string */
449 saveChar = collection[ic].part[0];
450 for (ip = 0; ip < collection[ic].oldColumns; ip++)
451 collection[ic].oldColumn[ip][strlen(collection[ic].oldColumn[ip]) - partLength] = 0;
452 qsort(collection[ic].oldColumn, collection[ic].oldColumns, sizeof(*collection[ic].oldColumn), string_cmpasc);
453 /* now restore the strings (column names) to original form */
454 for (ip = 0; ip < collection[ic].oldColumns; ip++)
455 collection[ic].oldColumn[ip][strlen(collection[ic].oldColumn[ip])] = saveChar;
456 } else {
457 qsort(collection[ic].oldColumn, collection[ic].oldColumns, sizeof(*collection[ic].oldColumn), string_cmpasc);
458 }
459 if (rootname)
460 continue;
461 *rootnames = collection[ic].oldColumns;
462 if (!(rootname = (char **)malloc(sizeof(*rootname) * (*rootnames)))) {
463 SDDS_Bomb("Memory allocation failure");
464 }
465 if (!(*units = (char **)malloc(sizeof(**units) * (*rootnames)))) {
466 SDDS_Bomb("Memory allocation failure");
467 }
468 for (ip = 0; ip < (*rootnames); ip++) {
469 if (SDDS_GetColumnInformation(SDDSin, "units", *units + ip, SDDS_GET_BY_NAME, collection[ic].oldColumn[ip]) != SDDS_STRING) {
470 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
471 }
472 if (collection[ic].flags & COLLECTION_EDIT) {
473 strcpy(editBuffer, collection[ic].oldColumn[ip]);
474 if (!edit_string(editBuffer, collection[ic].editCommand)) {
475 SDDS_Bomb("Problem editing column name.");
476 }
477 SDDS_CopyString(rootname + ip, editBuffer);
478 } else if (collection[ic].flags & COLLECTION_PREFIX) {
479 SDDS_CopyString(rootname + ip, collection[ic].oldColumn[ip] + partLength);
480 } else {
481 SDDS_CopyString(rootname + ip, collection[ic].oldColumn[ip]);
482 rootname[ip][strlen(rootname[ip]) - partLength] = 0;
483 }
484 }
485 }
486 if (!(*rootnames))
487 return NULL;
488
489 for (ic = 0; ic < collections; ic++) {
490 if (!collection[ic].oldColumns)
491 continue;
492 if (collection[ic].oldColumns != (*rootnames)) {
493 fprintf(stderr, "Error (sddscollect): Groups have different numbers of members\n");
494 for (ip = 0; ip < collections; ip++) {
495 fprintf(stderr, "%ld in %s\n", collection[ip].oldColumns,
496 collection[ip].part ? collection[ip].part : collection[ip].match);
497 }
498 exit(EXIT_FAILURE);
499 }
500 if (collection[ic].flags & COLLECTION_MATCH)
501 continue;
502 for (ip = 0; ip < collection[ic].oldColumns; ip++)
503 if (strstr(collection[ic].oldColumn[ip], rootname[ip]) == NULL) {
504 fprintf(stderr, "Error (sddscollect): Mismatch with rootname %s for column %s in group %s\n",
505 rootname[ip], collection[ic].oldColumn[ip],
506 collection[ic].part ? collection[ic].part : collection[ic].match);
507 /* about to bomb here, so it's okay to reuse these indices */
508 for (ic = 0; ic < collections; ic++) {
509 fprintf(stderr, "Group %s (%ld):\n",
510 collection[ic].part ? collection[ic].part : collection[ic].match, ic);
511 for (ip = 0; ip < collection[ic].oldColumns; ip++)
512 fprintf(stderr, " old column[%ld] = %s\n", ip, collection[ic].oldColumn[ip]);
513 }
514 exit(EXIT_FAILURE);
515 }
516 }
517
518 for (ic = 0; ic < collections; ic++) {
519 char *units;
520 int32_t type = 0;
521 long unitsMismatch;
522 if (!collection[ic].oldColumns)
523 continue;
524 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, collection[ic].oldColumn[0], collection[ic].newColumn) ||
525 (collection[ic].targetIndex = SDDS_GetColumnIndex(SDDSout, collection[ic].newColumn)) < 0 ||
526 SDDS_GetColumnInformation(SDDSout, "units", &units, SDDS_GET_BY_NAME, collection[ic].newColumn) != SDDS_STRING ||
527 SDDS_GetColumnInformation(SDDSout, "type", &type, SDDS_GET_BY_NAME, collection[ic].newColumn) != SDDS_LONG) {
528 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
529 }
530 collection[ic].size = SDDS_GetTypeSize(type);
531 unitsMismatch = 0;
532 for (ii = 1; ii < collection[ic].oldColumns; ii++) {
533 if (SDDS_CheckColumn(SDDSin, collection[ic].oldColumn[ii], NULL, type, stderr) == SDDS_CHECK_WRONGTYPE) {
534 fprintf(stderr, "Error (sddscollect): Inconsistent data types for suffix/prefix/match %s\n",
535 collection[ic].part ? collection[ic].part : collection[ic].match);
536 exit(EXIT_FAILURE);
537 }
538 if (SDDS_CheckColumn(SDDSin, collection[ic].oldColumn[ii], units, type, NULL) == SDDS_CHECK_WRONGUNITS)
539 unitsMismatch = 1;
540 }
541 if (unitsMismatch) {
542 if (warnings)
543 fprintf(stderr, "Warning (sddscollect): Inconsistent units for suffix/prefix %s\n", collection[ic].part);
544 if (!SDDS_ChangeColumnInformation(SDDSout, "units", "?", SDDS_BY_NAME, collection[ic].newColumn)) {
545 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
546 }
547 }
548 }
549
550 return rootname;
551}
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_CopyArrays(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:334
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
void * SDDS_GetInternalColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves an internal pointer to the data of a specified column, including all rows.
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
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_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_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
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_TransferAllArrayDefinitions(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, uint32_t mode)
Transfers all array definitions 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_DefineParameterLikeColumn(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Defines a parameter in the target dataset based on a column definition from the source dataset.
int32_t SDDS_GetParameterType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a parameter in the SDDS dataset by its index.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
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:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_GetTypeSize(int32_t type)
Retrieves the size in bytes of a specified SDDS data type.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
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
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
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
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.
int string_cmpasc(const void *a, const void *b)
Compare two strings in ascending order.
int wild_match(char *string, char *template)
Determine whether one string is a wildcard match for another.
Definition wild_match.c:49