SDDSlib
Loading...
Searching...
No Matches
sddschanges.c
Go to the documentation of this file.
1/**
2 * @file sddschanges.c
3 * @brief Analyze data from columns of an SDDS file to determine changes from the first page.
4 *
5 * This program processes an SDDS (Self Describing Data Set) file to compute changes
6 * in specified columns relative to baseline data, which can be provided either
7 * as a separate file or implicitly as the first page of the input file. The program
8 * supports various options to copy columns, pass data through, and configure output
9 * formatting.
10 *
11 * Features:
12 * - Compute changes in specified columns based on baseline data.
13 * - Optionally copy or pass through additional columns.
14 * - Support for parallel page processing and maintaining empty pages.
15 * - Configurable output order (row-major or column-major).
16 *
17 * Usage:
18 * sddschanges [OPTIONS] [<input>] [<output>]
19 *
20 * Options:
21 * -pipe=[input][,output]
22 * Use standard input/output for input and/or output.
23 *
24 * -changesIn=[exclude=<wildcard>,][,newType=<string>,]<column-names>
25 * Specify columns to compute changes for. Optionally exclude certain columns
26 * using wildcards and set a new data type for the resulting change columns.
27 *
28 * -copy=<column-names>
29 * Specify columns to copy from the first page of the input to all pages of the output.
30 * By default, only requested changes appear in the output.
31 *
32 * -pass=<column-names>
33 * Specify columns to pass through from each page of the input to each page of the output.
34 * By default, only requested changes appear in the output.
35 *
36 * -baseline=<filename>
37 * Specify a baseline SDDS file to compute changes against. If not provided,
38 * the first page of the input file is used as the baseline.
39 *
40 * -parallelPages
41 * When used with -baseline, compares the input and baseline files page-by-page.
42 * Otherwise, compares all input pages to the first page of the baseline data.
43 *
44 * -keepEmpties
45 * By default, empty pages in the input do not appear in the output.
46 * This option ensures that empty pages are emitted to the output.
47 *
48 * -majorOrder=row|column
49 * Specify the major order for writing the output file, either row-major or column-major.
50 *
51 * @copyright
52 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
53 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
54 *
55 * @license
56 * This file is distributed under the terms of the Software License Agreement
57 * found in the file LICENSE included with this distribution.
58 *
59 * @author M. Borland, C. Saunders, R. Soliday, H. Shang
60 */
61
62#include "mdb.h"
63#include "scan.h"
64#include "SDDS.h"
65#include "match_string.h"
66#include <ctype.h>
67
68/* Enumeration for option types */
69enum option_type {
70 SET_COPY,
71 SET_CHANGESIN,
72 SET_PASS,
73 SET_BASELINE,
74 SET_PIPE,
75 SET_PARALLELPAGES,
76 SET_KEEPEMPTIES,
77 SET_MAJOR_ORDER,
78 N_OPTIONS
79};
80
81char *option[N_OPTIONS] = {
82 "copy",
83 "changesin",
84 "pass",
85 "baseline",
86 "pipe",
87 "parallelpages",
88 "keepempties",
89 "majorOrder",
90};
91
92typedef struct
93{
94 char *columnName;
95 long optionCode, typeCode;
96 char *excludeName;
98
99/* This structure stores data necessary for accessing/creating SDDS columns and
100 * for computing a statistic.
101 */
102typedef struct
103{
104 char *sourceColumn, *resultColumn;
105 long optionCode, typeCode;
106 /* These store intermediate values during processing */
107 double *baseline, *change;
108 void *copy;
109 void *pass;
110 long type, newType;
112
113long addChangeRequests(CHANGE_REQUEST **request, long requests, char **item, long items, long code, char *excludeName, char *newType);
114CHANGE_DEFINITION *compileChangeDefinitions(SDDS_DATASET *inSet, long *changes, CHANGE_REQUEST *request, long requests);
115long setupOutputFile(SDDS_DATASET *outSet, char *output, SDDS_DATASET *inSet, CHANGE_DEFINITION *change, long changes, short columnMajorOrder);
116int64_t addBaselineData(CHANGE_DEFINITION *change, long changes, char *baseline, long page, int64_t lastRows);
117int64_t copyBaselineData(CHANGE_DEFINITION *change, long changes, SDDS_DATASET *dataset);
118void computeChanges(CHANGE_DEFINITION *change, long changes, SDDS_DATASET *inSet, int64_t rows);
119void outputChanges(CHANGE_DEFINITION *change, long changes, SDDS_DATASET *outSet, int64_t rows, SDDS_DATASET *inSet);
120long transferDefinitions(SDDS_DATASET *outSet, SDDS_DATASET *inSet, CHANGE_DEFINITION *change, long changes, long optionCode);
121
122static char *USAGE =
123 "Usage: sddschanges [OPTIONS] [<input>] [<output>]\n"
124 "\n"
125 "Options:\n"
126 " -pipe=[input][,output]\n"
127 " Use standard input/output for input and/or output.\n"
128 "\n"
129 " -changesIn=[exclude=<wildcard>,][,newType=<string>,]<column-names>\n"
130 " Specify columns to compute changes for. Optionally exclude certain columns\n"
131 " using wildcards and set a new data type for the resulting change columns.\n"
132 "\n"
133 " -copy=<column-names>\n"
134 " Specify columns to copy from the first page of the input to all pages of the output.\n"
135 " By default, only requested changes appear in the output.\n"
136 "\n"
137 " -pass=<column-names>\n"
138 " Specify columns to pass through from each page of the input to each page of the output.\n"
139 " By default, only requested changes appear in the output.\n"
140 "\n"
141 " -baseline=<filename>\n"
142 " Specify a baseline SDDS file to compute changes against. If not provided,\n"
143 " the first page of the input file is used as the baseline.\n"
144 "\n"
145 " -parallelPages\n"
146 " When used with -baseline, compares the input and baseline files page-by-page.\n"
147 " Otherwise, compares all input pages to the first page of the baseline data.\n"
148 "\n"
149 " -keepEmpties\n"
150 " By default, empty pages in the input do not appear in the output.\n"
151 " This option ensures that empty pages are emitted to the output.\n"
152 "\n"
153 " -majorOrder=row|column\n"
154 " Specify the major order for writing the output file, either row-major or column-major.\n"
155 "\n"
156 "Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
157
158int main(int argc, char **argv) {
159 CHANGE_DEFINITION *change;
160 long changes, requests;
161 CHANGE_REQUEST *request;
162 SCANNED_ARG *scanned; /* structure for scanned arguments */
163 SDDS_DATASET inSet, outSet;
164 long i_arg, code, parallelPages, keepEmpties, i;
165 int64_t baselineRows, rows, lastRows;
166 char *input, *baseline, *output;
167 unsigned long pipeFlags, majorOrderFlag;
168 char *excludeName = NULL;
169 char *ptr = NULL;
170 short columnMajorOrder = -1;
171
173 argc = scanargs(&scanned, argc, argv);
174 if (argc < 3) {
175 bomb(NULL, USAGE);
176 }
177
178 input = output = baseline = NULL;
179 change = NULL;
180 request = NULL;
181 changes = requests = baselineRows = 0;
182 pipeFlags = 0;
183 parallelPages = keepEmpties = 0;
184
185 for (i_arg = 1; i_arg < argc; i_arg++) {
186 if (scanned[i_arg].arg_type == OPTION) {
187 /* Process options here */
188 switch (code = match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
189 case SET_MAJOR_ORDER:
190 majorOrderFlag = 0;
191 scanned[i_arg].n_items -= 1;
192 if (scanned[i_arg].n_items > 0 &&
193 (!scanItemList(&majorOrderFlag, scanned[i_arg].list + 1, &scanned[i_arg].n_items,
194 0, "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
195 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
196 SDDS_Bomb("Invalid -majorOrder syntax/values");
197 }
198 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
199 columnMajorOrder = 1;
200 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
201 columnMajorOrder = 0;
202 break;
203 case SET_COPY:
204 case SET_CHANGESIN:
205 case SET_PASS:
206 if (scanned[i_arg].n_items < 2) {
207 fprintf(stderr, "Error: Invalid -%s syntax\n", option[code]);
208 exit(EXIT_FAILURE);
209 }
210 if (code == SET_CHANGESIN) {
211 long offset;
212 char *newTypeName;
213 char *changeOption[2] = {"exclude", "newtype"};
214#define CHANGE_EXCLUDE 0
215#define CHANGE_NEWTYPE 1
216#define N_CHANGE_OPTIONS 2
217 excludeName = newTypeName = NULL;
218 for (offset = 1; offset < scanned[i_arg].n_items; offset++) {
219 if ((ptr = strchr(scanned[i_arg].list[offset], '='))) {
220 *ptr = '\0';
221 switch (match_string(scanned[i_arg].list[offset], changeOption, N_CHANGE_OPTIONS, 0)) {
222 case CHANGE_EXCLUDE:
223 SDDS_CopyString(&excludeName, ++ptr);
224 break;
225 case CHANGE_NEWTYPE:
226 SDDS_CopyString(&newTypeName, ++ptr);
227 break;
228 default:
229 break;
230 }
231 } else {
232 break;
233 }
234 }
235 requests = addChangeRequests(&request, requests, scanned[i_arg].list + offset,
236 scanned[i_arg].n_items - offset, code, excludeName, newTypeName);
237 } else {
238 requests = addChangeRequests(&request, requests, scanned[i_arg].list + 1,
239 scanned[i_arg].n_items - 1, code, NULL, NULL);
240 }
241 break;
242 case SET_BASELINE:
243 if (scanned[i_arg].n_items != 2)
244 SDDS_Bomb("Invalid -baseline syntax");
245 SDDS_CopyString(&baseline, scanned[i_arg].list[1]);
246 break;
247 case SET_PIPE:
248 if (!processPipeOption(scanned[i_arg].list + 1, scanned[i_arg].n_items - 1, &pipeFlags))
249 SDDS_Bomb("Invalid -pipe syntax");
250 break;
251 case SET_PARALLELPAGES:
252 parallelPages = 1;
253 break;
254 case SET_KEEPEMPTIES:
255 keepEmpties = 1;
256 break;
257 default:
258 fprintf(stderr, "Error: Unknown option '%s' given\n", scanned[i_arg].list[0]);
259 exit(EXIT_FAILURE);
260 break;
261 }
262 } else {
263 /* Argument is filename */
264 if (!input)
265 SDDS_CopyString(&input, scanned[i_arg].list[0]);
266 else if (!output)
267 SDDS_CopyString(&output, scanned[i_arg].list[0]);
268 else
269 SDDS_Bomb("Too many filenames provided");
270 }
271 }
272
273 if (parallelPages && !baseline)
274 SDDS_Bomb("-parallelPages only makes sense with -baseline");
275
276 processFilenames("sddschanges", &input, &output, pipeFlags, 0, NULL);
277
278 if (!requests)
279 SDDS_Bomb("No changes requested");
280
281 if (!SDDS_InitializeInput(&inSet, input))
282 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
283
284 if (!(change = compileChangeDefinitions(&inSet, &changes, request, requests)))
285 SDDS_Bomb("Unable to compile definitions");
286
287 if (!setupOutputFile(&outSet, output, &inSet, change, changes, columnMajorOrder)) {
288 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
289 SDDS_Bomb("Unable to setup output file");
290 }
291
292 if (baseline && !parallelPages)
293 baselineRows = addBaselineData(change, changes, baseline, 0, 0);
294
295 lastRows = 0;
296 while ((code = SDDS_ReadPage(&inSet)) > 0) {
297 rows = SDDS_CountRowsOfInterest(&inSet);
298 if (baseline && parallelPages)
299 baselineRows = addBaselineData(change, changes, baseline, code, lastRows);
300 if (!baseline && code == 1) {
301 baselineRows = copyBaselineData(change, changes, &inSet);
302 continue;
303 }
304 if (rows != baselineRows)
305 SDDS_Bomb("Number of rows in file changed");
306 if (rows)
307 computeChanges(change, changes, &inSet, rows);
308 if (rows || keepEmpties)
309 outputChanges(change, changes, &outSet, rows, &inSet);
310 lastRows = rows;
311 }
312 if (!SDDS_Terminate(&inSet) || !SDDS_Terminate(&outSet)) {
313 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
314 exit(EXIT_FAILURE);
315 }
316 if (change) {
317 for (i = 0; i < changes; i++) {
318 if (change[i].baseline)
319 free(change[i].baseline);
320 if (change[i].change)
321 free(change[i].change);
322 }
323 free(change);
324 }
325 if (input)
326 free(input);
327 if (output)
328 free(output);
329 if (baseline)
330 free(baseline);
331 if (request)
332 free(request);
333 free_scanargs(&scanned, argc);
334 return EXIT_SUCCESS;
335}
336
337int64_t addBaselineData(CHANGE_DEFINITION *change, long changes, char *baseline, long page, int64_t lastRows) {
338 static SDDS_DATASET dataset;
339 long i, code;
340 int64_t rows;
341 rows = 0;
342
343 if (page == 0 || page == 1) {
344 if (!SDDS_InitializeInput(&dataset, baseline))
345 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
346 }
347 if ((code = SDDS_ReadPage(&dataset)) <= 0 || (rows = SDDS_CountRowsOfInterest(&dataset)) < 0) {
348 SDDS_SetError("Problem reading (next) page of baseline data file");
349 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
350 }
351 if (page && code != page)
352 SDDS_Bomb("Page mixup in baseline file");
353 for (i = 0; i < changes; i++) {
354 if (change[i].optionCode == SET_CHANGESIN) {
355 if (change[i].baseline) {
356 if (page > 1)
357 free(change[i].baseline);
358 change[i].baseline = NULL;
359 }
360 if (rows && !(change[i].baseline = SDDS_GetColumnInDoubles(&dataset, change[i].sourceColumn))) {
361 fprintf(stderr, "Problem reading baseline data\n");
362 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
363 }
364 } else if (change[i].optionCode == SET_COPY) {
365 if (change[i].copy) {
366 if (page > 1) {
367 if (change[i].type == SDDS_STRING && lastRows)
368 SDDS_FreeStringArray(change[i].copy, lastRows);
369 }
370 free(change[i].copy);
371 change[i].copy = NULL;
372 }
373 if (rows && !(change[i].copy = SDDS_GetColumn(&dataset, change[i].sourceColumn))) {
374 fprintf(stderr, "Problem reading baseline data\n");
375 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
376 }
377 }
378 }
379 return rows;
380}
381
382int64_t copyBaselineData(CHANGE_DEFINITION *change, long changes, SDDS_DATASET *dataset) {
383 long i;
384 int64_t rows;
385
386 if (!(rows = SDDS_CountRowsOfInterest(dataset)))
387 SDDS_Bomb("No data in first page of input file");
388 for (i = 0; i < changes; i++) {
389 if (change[i].optionCode == SET_CHANGESIN) {
390 if (!(change[i].baseline = SDDS_GetColumnInDoubles(dataset, change[i].sourceColumn))) {
391 fprintf(stderr, "Problem reading baseline data\n");
392 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
393 }
394 } else if (change[i].optionCode == SET_COPY) {
395 if (!(change[i].copy = SDDS_GetColumn(dataset, change[i].sourceColumn))) {
396 fprintf(stderr, "Problem reading baseline data\n");
397 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
398 }
399 }
400 }
401 return rows;
402}
403
404void computeChanges(CHANGE_DEFINITION *change, long changes, SDDS_DATASET *inSet, int64_t rows) {
405 double *data;
406 long i;
407 int64_t j;
408
409 for (i = 0; i < changes; i++) {
410 switch (change[i].optionCode) {
411 case SET_COPY:
412 break;
413 case SET_PASS:
414 break;
415 case SET_CHANGESIN:
416 if (!(data = SDDS_GetColumnInDoubles(inSet, change[i].sourceColumn))) {
417 fprintf(stderr, "Problem reading input data\n");
418 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
419 }
420 if (change[i].change)
421 free(change[i].change);
422 change[i].change = (double *)tmalloc(sizeof(*(change[i].change)) * rows);
423 for (j = 0; j < rows; j++) {
424 change[i].change[j] = data[j] - change[i].baseline[j];
425 }
426 free(data);
427 break;
428 }
429 }
430}
431
432void outputChanges(CHANGE_DEFINITION *change, long changes, SDDS_DATASET *outSet, int64_t rows, SDDS_DATASET *inSet) {
433 long i;
434 void *data;
435
436 if (!SDDS_StartPage(outSet, rows))
437 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
438
439 if (!SDDS_CopyParameters(outSet, inSet))
440 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
441
442 if (rows) {
443 for (i = 0; i < changes; i++) {
444 switch (change[i].optionCode) {
445 case SET_CHANGESIN:
446 if (!SDDS_SetColumnFromDoubles(outSet, SDDS_SET_BY_NAME, change[i].change, rows, change[i].resultColumn))
447 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
448 break;
449 case SET_COPY:
450 if (!SDDS_SetColumn(outSet, SDDS_SET_BY_NAME, change[i].copy, rows, change[i].resultColumn))
451 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
452 break;
453 case SET_PASS:
454 if (!(data = SDDS_GetInternalColumn(inSet, change[i].resultColumn)) ||
455 !SDDS_SetColumn(outSet, SDDS_SET_BY_NAME, data, rows, change[i].resultColumn))
456 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
457 break;
458 }
459 }
460 }
461 if (!SDDS_WritePage(outSet))
462 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
463}
464
465long addChangeRequests(CHANGE_REQUEST **request, long requests, char **item, long items, long code, char *excludeName, char *newTypeName) {
466 long i;
467 *request = SDDS_Realloc(*request, sizeof(**request) * (requests + items));
468 for (i = 0; i < items; i++) {
469 (*request)[i + requests].columnName = item[i];
470 (*request)[i + requests].optionCode = code;
471 (*request)[i + requests].excludeName = excludeName;
472 if (newTypeName) {
473 if (((*request)[i + requests].typeCode = SDDS_IdentifyType(newTypeName)) == 0) {
474 char buffer[16384];
475 snprintf(buffer, sizeof(buffer), "Unknown type given: %s", newTypeName);
476 SDDS_Bomb(buffer);
477 }
478 } else {
479 (*request)[i + requests].typeCode = -1;
480 }
481 }
482 return items + requests;
483}
484
485CHANGE_DEFINITION *compileChangeDefinitions(SDDS_DATASET *inSet, long *changes, CHANGE_REQUEST *request, long requests) {
486 CHANGE_DEFINITION *change;
487 long iReq, iChange, iName, index;
488 int32_t columnNames;
489 char s[SDDS_MAXLINE];
490 char **columnName;
491
492 change = tmalloc(sizeof(*change) * requests);
493 *changes = iChange = 0;
494 for (iReq = 0; iReq < requests; iReq++) {
495 if (iChange >= *changes)
496 change = SDDS_Realloc(change, sizeof(*change) * (*changes += 10));
497 if (!has_wildcards(request[iReq].columnName)) {
498 if ((index = SDDS_GetColumnIndex(inSet, request[iReq].columnName)) < 0) {
499 sprintf(s, "Error: Column '%s' not found in input file", request[iReq].columnName);
500 SDDS_SetError(s);
501 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
502 }
503 change[iChange].sourceColumn = request[iReq].columnName;
504 change[iChange].optionCode = request[iReq].optionCode;
505 change[iChange].change = change[iChange].baseline = NULL;
506 change[iChange].type = SDDS_GetColumnType(inSet, index);
507 if (change[iChange].optionCode == SET_CHANGESIN && !SDDS_NUMERIC_TYPE(SDDS_GetColumnType(inSet, index))) {
508 fprintf(stderr, "Error: Column '%s' is non-numeric. Cannot compute changes.\n", change[iChange].sourceColumn);
509 exit(EXIT_FAILURE);
510 }
511 change[iChange].copy = change[iChange].pass = NULL;
512 change[iChange].baseline = change[iChange].change = NULL;
513 change[iChange].newType = request[iReq].typeCode;
514 iChange++;
515 } else {
516 SDDS_SetColumnFlags(inSet, 0);
517 if (!SDDS_SetColumnsOfInterest(inSet, SDDS_MATCH_STRING, request[iReq].columnName, SDDS_OR))
518 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
519 if (request[iReq].excludeName) {
520 if (!SDDS_SetColumnsOfInterest(inSet, SDDS_MATCH_STRING, request[iReq].excludeName, SDDS_NEGATE_MATCH | SDDS_AND))
521 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
522 }
523 if (!(columnName = SDDS_GetColumnNames(inSet, &columnNames))) {
524 sprintf(s, "No columns selected for wildcard sequence '%s'", request[iReq].columnName);
525 SDDS_SetError(s);
526 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
527 }
528 if (iChange + columnNames > *changes)
529 change = SDDS_Realloc(change, sizeof(*change) * (*changes = iChange + columnNames + 10));
530 for (iName = 0; iName < columnNames; iName++) {
531 change[iChange + iName].sourceColumn = columnName[iName];
532 change[iChange + iName].optionCode = request[iReq].optionCode;
533 change[iChange + iName].change = change[iChange + iName].baseline = NULL;
534 change[iChange + iName].type = SDDS_GetNamedColumnType(inSet, change[iChange].sourceColumn);
535 if (change[iChange].optionCode == SET_CHANGESIN && !SDDS_NUMERIC_TYPE(SDDS_GetNamedColumnType(inSet, change[iChange].sourceColumn))) {
536 fprintf(stderr, "Error: Column '%s' is non-numeric. Cannot compute changes.\n", change[iChange].sourceColumn);
537 exit(EXIT_FAILURE);
538 }
539 change[iChange].copy = change[iChange].pass = NULL;
540 change[iChange].baseline = change[iChange].change = NULL;
541 change[iChange].newType = request[iReq].typeCode;
542 }
543 iChange += columnNames;
544 free(columnName);
545 }
546 }
547
548 *changes = iChange;
549 for (iChange = 0; iChange < *changes; iChange++) {
550 switch (change[iChange].optionCode) {
551 case SET_COPY:
552 case SET_PASS:
553 strcpy(s, change[iChange].sourceColumn);
554 break;
555 case SET_CHANGESIN:
556 sprintf(s, "ChangeIn%s", change[iChange].sourceColumn);
557 break;
558 }
559 if (!SDDS_CopyString(&change[iChange].resultColumn, s))
560 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
561 }
562 return change;
563}
564
565long setupOutputFile(SDDS_DATASET *outSet, char *output, SDDS_DATASET *inSet, CHANGE_DEFINITION *change, long changes, short columnMajorOrder) {
566 long i;
567 int32_t parameters;
568 char **parameter = NULL, s[SDDS_MAXLINE];
569
570 if (!SDDS_InitializeOutput(outSet, SDDS_BINARY, 0, NULL, "sddschanges output", output))
571 return 0;
572 if (columnMajorOrder != -1)
573 outSet->layout.data_mode.column_major = columnMajorOrder;
574 else
575 outSet->layout.data_mode.column_major = inSet->layout.data_mode.column_major;
576 if (!transferDefinitions(outSet, inSet, change, changes, SET_CHANGESIN))
577 return 0;
578 if (!transferDefinitions(outSet, inSet, change, changes, SET_COPY))
579 return 0;
580 if (!transferDefinitions(outSet, inSet, change, changes, SET_PASS))
581 return 0;
582 if ((parameter = SDDS_GetParameterNames(inSet, &parameters)) && parameters) {
583 for (i = 0; i < parameters; i++)
584 if (!SDDS_TransferParameterDefinition(outSet, inSet, parameter[i], NULL))
585 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
586 for (i = 0; i < parameters; i++)
587 free(parameter[i]);
588 free(parameter);
589 }
590 if (!SDDS_WriteLayout(outSet)) {
591 sprintf(s, "Unable to complete setup of output file");
592 SDDS_SetError(s);
593 return 0;
594 }
595 return 1;
596}
597
598long transferDefinitions(SDDS_DATASET *outSet, SDDS_DATASET *inSet, CHANGE_DEFINITION *change, long changes, long optionCode) {
599 long column;
600 char s[SDDS_MAXLINE], *symbol;
601
602 for (column = 0; column < changes; column++) {
603 if (optionCode != change[column].optionCode)
604 continue;
605 if (!SDDS_TransferColumnDefinition(outSet, inSet, change[column].sourceColumn, change[column].resultColumn)) {
606 sprintf(s, "Problem transferring definition of column '%s'", change[column].sourceColumn);
607 SDDS_SetError(s);
608 return 0;
609 }
610 /* THIS CODE IS BROKEN
611 if (change[column].newType > 0 && change[column].newType != change[column].type)
612 {
613 fprintf(stderr, "change[%d].newType=%d change[%d].type=%d\n", column, change[column].newType, column, change[column].type);
614 if (!SDDS_ChangeColumnInformation(outSet, "type", SDDS_GetTypeName(change[column].newType), SDDS_PASS_BY_STRING | SDDS_SET_BY_NAME, change[column].resultColumn))
615 {
616 sprintf(s, "Problem changing type of column %s to make %s\n", change[column].sourceColumn, change[column].resultColumn);
617 SDDS_SetError(s);
618 return 0;
619 }
620 }
621 */
622 if (!SDDS_ChangeColumnInformation(outSet, "description", NULL, SDDS_SET_BY_NAME, change[column].resultColumn) ||
623 SDDS_GetColumnInformation(outSet, "symbol", &symbol, SDDS_BY_NAME, change[column].resultColumn) != SDDS_STRING) {
624 sprintf(s, "Unable to get/modify column '%s' information", change[column].sourceColumn);
625 SDDS_SetError(s);
626 return 0;
627 }
628 if (!symbol)
629 SDDS_CopyString(&symbol, change[column].sourceColumn);
630 switch (change[column].optionCode) {
631 case SET_COPY:
632 case SET_PASS:
633 strcpy(s, symbol);
634 break;
635 case SET_CHANGESIN:
636 sprintf(s, "ChangeIn[%s]", symbol);
637 break;
638 default:
639 SDDS_Bomb("Invalid option code in transferDefinitions");
640 break;
641 }
642 if (!SDDS_ChangeColumnInformation(outSet, "symbol", s, SDDS_BY_NAME, change[column].resultColumn))
643 return 0;
644 }
645 return 1;
646}
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.
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.
int32_t SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Sets the acceptance flags for columns based on specified naming criteria.
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_SetColumnFlags(SDDS_DATASET *SDDS_dataset, int32_t column_flag_value)
Sets the acceptance flags for all columns in the current data table of a data set.
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_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_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.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
int32_t SDDS_GetNamedColumnType(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the data type of a column in the SDDS dataset by its name.
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.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
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_IdentifyType(char *typeName)
Identifies the SDDS data type based on its string name.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
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_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
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
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.
int has_wildcards(char *template)
Check if a template string contains any wildcard characters.
Definition wild_match.c:498